package cluster

import (
	"encoding/json"
	"github.com/samuel/go-zookeeper/zk"
	log "github.com/sirupsen/logrus"
	"net"
	"strings"
	"xc/app/zookeeper"
)

// Node 集群节点
type Node struct {
	name    string                 //节点名字
	leader  bool                   //是否是leader
	path    string                 //zk路径
	data    map[string]interface{} //zk数据，保持ip地址等相关信息
	flags   int32                  //zk标示
	acl     []zk.ACL               //zk权限
	version int32                  //zk版本
}

var node *Node

//InitNode 初始化节点
func InitNode() {
	n := new(Node)
	n.initData()
	n.check()

	node = n
}

//initData 初始化数据
func (n *Node) initData() {
	n.leader = false
	n.path = zookeeper.GetNodePath()
	n.data = n.getDataInfo()
	n.flags = zookeeper.FlagEphemeralAndSequence
	n.acl = zk.WorldACL(zk.PermAll)
	n.version = 1
}

// 检查当前节点
// 如果节点不存在就创建
func (n *Node) check() {
	data, _ := json.Marshal(n.data)
	ret, err := zookeeper.Connect().Create(n.path, data, n.flags, n.acl)
	if err != nil {
		log.Panic("[node]节点创建失败", err.Error())
	}
	log.Info("[node]创建节点成功：", ret)

	n.name = strings.ReplaceAll(ret, zookeeper.GetNodePath(), "")
}

func (n *Node) update() {
	// todo:更新node信息
}

//getDataInfo 获取data数据信息
// 初始化的时候某些数据不存在，在check成功以后需要再次更新，比如name、leader
func (n *Node) getDataInfo() map[string]interface{} {
	data := make(map[string]interface{})
	data["name"] = n.name
	data["ip"] = n.getIpAddress()
	data["leader"] = n.leader

	return data
}

//getIpAddress 获取IP地址
func (n *Node) getIpAddress() string {
	netInterfaces, err := net.Interfaces()
	if err != nil {
		log.Error("net.Interfaces failed, err:", err.Error())
		return ""
	}

	for i := 0; i < len(netInterfaces); i++ {
		if (netInterfaces[i].Flags & net.FlagUp) != 0 {
			addressList, _ := netInterfaces[i].Addrs()

			for _, address := range addressList {
				if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
					if ipnet.IP.To4() != nil {
						log.Info("[node]", ipnet.IP.String())
						return ipnet.IP.String()
					}
				}
			}
		}
	}

	return ""
}
